/*********************************************************************************************************
 *  ------------------------------------------------------------------------------------------------------
 *  file description
 *  ------------------------------------------------------------------------------------------------------
 *         \file  iterator.h
 *        \brief  This is a general-purpose C language iterator module
 *       \author  Lamdonn
 *        \email  Lamdonn@163.com
 *      \version  1.0.0
 *      \license  GPL2
 *    \copyright  Copyright (C) 2023 Lamdonn.
 ********************************************************************************************************/
#ifndef __iterator_H
#define __iterator_H

/* the base parent class for all containers in vlib */
typedef struct 
{
    char ident;                         /* ident of object, in general, no access is required */
    void *base;                         /* base address of object */
    int dsize;                          /* size of data */
    int size;                           /* size of object */
} VOBJECT, *vobject_t;

/* iterator type define */
typedef struct
{
    vobject_t object;                   /* permissions: readable not writable，the object recorded by the current iterator */
    void *node;                         /* permissions: not readable not writable，iterate position node */
    int pos;                            /* permissions: readable not writable，current position */
} iterator;

/* vlib container object */
#define VTYPE_UNKNOW                    (0) /* unknow */
#define VTYPE_STR                       (1) /* str */
#define VTYPE_VECTOR                    (2) /* vector */
#define VTYPE_QUEUE                     (3) /* queue */
#define VTYPE_STACK                     (4) /* stack */
#define VTYPE_DEQUE                     (5) /* deque */
#define VTYPE_LIST                      (6) /* list */
#define VTYPE_SET                       (7) /* set */
#define VTYPE_MAP                       (8) /* map */

/* vlib container type name */
extern const char *vtype_table[9];

/** 
 *  \brief get vlib container object
 *  \param[in] object: vlib container object
 *  \return type of vlib container, as VTYPE_XXX
 */
int vtype(vobject_t object);

/** 
 *  \brief create and initialize iterator, the simpler macro definition method it() is recommended
 *  \param[in] object: container object
 *  \param[in] pos: pos of container, usually 0 is used to locate begin and -1 is used to locate end
 *  \return iterator
 */
iterator iterator_create(vobject_t object, int pos);

/** 
 *  \brief determine whether the iterator is valid, the simpler macro definition method it_valid() is recommended
 *  \param[in] it: address of iterator
 *  \return 1 valid or 0 not valid
 */
int iterator_valid(iterator *it);

/** 
 *  \brief move iterator, the simpler macro definition method it_move() is recommended
 *  \param[in] it: address of iterator
 *  \param[in] step: steps moved, positive numbers move backward, negative numbers move forward
 *  \return steps moved or 0 fail
 */
int iterator_move(iterator *it, int step);

/** 
 *  \brief get the address of iterator key, the simpler macro definition method it_key() is recommended
 *  \param[in] it: address of iterator
 *  \return iterator key
 */
void* iterator_key(iterator *it);

/** 
 *  \brief get the address of iterator value, the simpler macro definition method it_value() is recommended
 *  \param[in] it: address of iterator
 *  \return iterator value
 */
void* iterator_value(iterator *it);

/** 
 *  \brief create and initialize iterator
 *  \param[in] object: container object
 *  \param[in] pos: pos of container, usually 0 is used to locate begin and -1 is used to locate end
 *  \return iterator
 */
#define it(object, pos)                 iterator_create((vobject_t)(object), (pos))

/** 
 *  \brief go to the begin of the container
 *  \param[in] object: container object
 *  \return iterator
 */
#define it_begin(object)                it(object, 0)

/** 
 *  \brief go to the end of the container
 *  \param[in] object: container object
 *  \return end address
 */
#define it_end(object)                  it(object, -1)

/** 
 *  \brief determine whether the iterator is valid
 *  \param[in] it: iterator
 *  \return 1 valid or 0 not valid
 */
#define it_valid(it)                    iterator_valid(&(it))

/** 
 *  \brief move iterator
 *  \param[in] it: iterator
 *  \param[in] step: steps moved, positive numbers move backward, negative numbers move forward
 *  \return steps moved or 0 fail
 */
#define it_move(it, step)               iterator_move(&(it), (step))

/** 
 *  \brief get the address of iterator key, for example, the key of list is index, and the key of map is map_key_t
 *  \param[in] it: iterator
 *  \return iterator key
 */
#define it_key(it)                      iterator_key(&(it))

/** 
 *  \brief get the address of iterator value
 *  \param[in] it: iterator
 *  \return iterator value
 */
#define it_value(it)                    iterator_value(&(it))

/** 
 *  \brief get the size of iterator
 *  \param[in] it: iterator
 *  \return iterator size
 */
#define it_size(it)                     ((it).object->size)

/** 
 *  \brief get vlib container object name
 *  \param[in] object: vlib container object
 *  \return object name
 */
#define vtype_name(object)              ((const char *)vtype_table[vtype((vobject_t)(object))])

#endif 
